#ifndef VMPF
#define VMPF

#include "Base.hpp"


//Interface begins........................................................


	//Variable search: ________________
		struct sRecord;
			typedef sRecord* ptrRecord;

		typedef StrHashmap<sRecord> cVariables;
			typedef cVariables* ptrVariables;

	//RET Node Base:   ________________
		class cRETNode;
			typedef cRETNode* ptrRETNode;
		typedef cSet<ptrRETNode> cRETNodeList;

	//Dough:   ________________________
		struct cDough;
			typedef cDough* ptrDough;

	//Dough Extended:
		typedef cArray<void*> cExtendedTable;
			typedef cExtendedTable* ptrExtendedTable;
		//========Extended consts========
			//Type info: 
			const int EXT_TYPE=0;              //Describe the type of the target dough.
				const int EXT_TV_NUMBER=0;
				const int EXT_TV_TEXT=1;
			const int EXT_TYPEV=1;             //Value.

			//UsrDough Param name list:
			const int EXT_PARAM=2;
				typedef cList<cText> Params;
				typedef Params* ptrParams;

			//Array dough:
			const int EXT_ARRAYTYPE=3;
			const int EXT_ARRAY=4;
				typedef cArray<sRecord> dArray;
					typedef dArray* ptrdArray;
		//===============================
	//End of Dough Extended.


	//Parsed Element Tree___________
		class cParsedElement;
			typedef cParsedElement*			ptrParsedElement;
			typedef cList<ptrParsedElement> cListElements;
			typedef cListElements*			ptrListElements;

		class cOperation;
			typedef cOperation*	ptrOperation;


	//AWScript Parser:
		class cIdentity;
			typedef cIdentity* ptrIdentity;
		typedef cList<ptrIdentity> ListIdentity;

	//Operation:----
	//Operation Typedefs:
		typedef 
			sRecord (*funOperationMethod)(ptrRETNode,ptrParsedElement,void*);		//Operation Function.
		typedef
			void (*funPreLining)(ListIdentity*);
		typedef
			void (*funPostLining)(ListIdentity*);
		typedef
			ptrParsedElement (*funMakingTree)(ptrText, ptrIdentity, ptrParsedElement);
		typedef
			void (*funFound)(ptrIdentity);


//End of Interface.............

		//
		//
		//
		//
		//
		//
		//

//Implementation begin.............................

	//Implementation of ParsedElement Tree.
	class cParsedElement{
	public:
		ptrOperation		Operation;
		void*				Extended;

		cListElements		SubElements;
		ptrParsedElement	father;

		cParsedElement(ptrOperation op=NULL):Operation(op){};
		
		ptrParsedElement cloneTree(){
			ptrParsedElement ret=new cParsedElement();
			ret->father=NULL;
			ret->Operation=this->Operation;
			ret->Extended=this->Extended;
			for (int i=0; i<SubElements.length(); ++i)
				ret->SubElements.push(SubElements[i]->cloneTree());
			return ret;
		}

		void push(ptrParsedElement what){
			SubElements.push(what);
			what->father=this;
		};
	};

	//Implementation of Dough ------------------
	//Need to complete Rubbish recycler.
		struct cDough{
			ptrVariables			Statics;
			ptrParsedElement		ParsedTree;
			ptrExtendedTable		Extended;
		};

		ptrDough CreateDough(ptrParsedElement pe=NULL){
			ptrDough tmp=new cDough();
			tmp->Statics=new cVariables();
			tmp->Extended=new cExtendedTable();
			tmp->ParsedTree=pe;
			return tmp;
		}

		ptrDough CreateNumberDough(ptrNumber what){
			ptrDough tmp=CreateDough();
			tmp->Extended->push(EXT_TYPE,(void*)EXT_TV_NUMBER);

			if (what){
				ptrNumber store=new Number(*what);
				tmp->Extended->push(EXT_TYPEV,(void*)store);
			}
			else
				tmp->Extended->push(EXT_TYPEV,NULL);
			return tmp;
		};

		ptrDough CreateTextDough(ptrText what){
			ptrDough tmp=CreateDough();
			tmp->Extended->push(EXT_TYPE,(void*)EXT_TV_TEXT);

			if (what){
				ptrText store=new cText(*what);
				tmp->Extended->push(EXT_TYPEV,(void*)store);
			}
			else
				tmp->Extended->push(EXT_TYPEV,NULL);
			return tmp;
		};


	//Implementaion of Operation   --------------
		class cOperation{
		public:
			cText					Name;				//
			cText					Formula;			//RegularExpression of this Operation
			funOperationMethod		onEvaluate;			//What to do during Evaluation
			cExtendedTable			Extended;			//

			funPreLining			onPreLining;		//Called before RegExp
			funPostLining			onPostLining;		//Called After RegExp
			funMakingTree			onMakingTree;		//Called when making tree.
			funFound				onFoundIdentity;

			cOperation():onPreLining(NULL),onPostLining(NULL),onMakingTree(NULL),onFoundIdentity(NULL){};

			cOperation(const cText& a, const cText& b, const funOperationMethod& c,
				funPreLining e=NULL, funPostLining f=NULL, funMakingTree g=NULL, funFound h=NULL):
			Name(a),Formula(b),onEvaluate(c),onPreLining(e),onPostLining(f),onMakingTree(g),onFoundIdentity(h)
			{};
		};
	
		struct sRecord{
			ptrDough dough; //rvalue
			sRecord*  var;  //lvalue
			sRecord(ptrDough _dough=NULL, sRecord* _var=NULL):
				dough(_dough),var(_var)
			{};
		};

		typedef sRecord* ptrRecord;
	

	//AWScript Parser:              ------------
		class cIdentity{
		public:
			cRange					Range;
			ptrOperation			Operation;		//Operation refered to the Parsed Statemnet.
			ListIdentity*			SubIdentities;	//What 
			cText*					Identifier;		//How to represent this Operation?
			void*					Extended;
			//---
			cIdentity(const cRange& _range, ptrText _identifier, const ptrOperation& _operation,ListIdentity* _SubIdentities):
				Range(_range),
				Identifier(_identifier),
				Operation(_operation),
				SubIdentities(_SubIdentities),
				Extended(NULL)
			{};
			cIdentity(const cRange& a,ptrText b, const ptrOperation& c):
				Range(a),Identifier(b),Operation(c)
			{};

			
			~cIdentity(){
				delete SubIdentities;
			};
		};

		inline ptrIdentity ReturnIdentity(const cRange& range, ptrText identifier, const ptrOperation& operation, ListIdentity* subs){
			return new cIdentity(range,identifier,operation,subs);
		};


	
	//RET    ---------------------------------------
		class cRETNode{
		public:
			ptrDough		Dough;		//to DM which dough the Node refers to.
			cVariables		Locals;		//local variable storage
			ptrRETNode		Caller;		//to by whom the dough called
			cRETNodeList	Callee;
			cExtendedTable	Extended;

			cRETNode(ptrDough _dough, ptrRETNode _father):
				Dough(_dough),Caller(_father)
			{};

			ptrRETNode Append(ptrDough what){
				ptrRETNode tmp=new cRETNode(what,this);
				Callee.push(tmp);
				return tmp;
			};
		};

		//"" is false, 0 is false, false is false.
	/*
		bool Boolean(ptrDough what){
			//if (what->
		}
		*/

	//Helper Marco & Functions:

		#define eval(ret,pe,ext) (pe)->Operation->onEvaluate((ret),(pe),(ext))
		#define assignEvalR(ret,pe,ext,route,Result) try{(Result)=(pe)->Operation->onEvaluate((ret),(pe),(ext));}catch(route Cast)
		#define RetEva(ret,pe,ext,route) try{return (pe)->Operation->onEvaluate((ret),(pe),(ext));}catch(route Cast)

		//
		
		inline Number getNumber(ptrDough what){
			if ((int)(what->Extended->search(EXT_TYPE))==EXT_TV_NUMBER)
				return *((Number*)(what->Extended->search(EXT_TYPEV)));
		}
		inline ptrText getText(ptrDough what){
			if ((int)(what->Extended->search(EXT_TYPE))==EXT_TV_TEXT)
				return ((cText*)(what->Extended->search(EXT_TYPEV)));
		}

//End of Implementation...........
#endif